package cn.bwq;

import cn.bwq.entity.M3U8Object;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class MainFrame extends JFrame {

    private static java.util.List<M3U8Object> m3u8Files;

    public MainFrame() {
        m3u8Files = new java.util.ArrayList<>();
        setTitle("M3U8视频合并");
        setSize(400,730);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new FlowLayout());

        JButton jButton = new JButton("视频位置");
        add(jButton);

        JTextField jTextField = new JTextField();
        jTextField.setPreferredSize(new Dimension(380, 30));
        jTextField.setText("点击选取视频所在文件夹");
        jTextField.setEditable(false);
        add(jTextField);

        JButton jButton3 = new JButton("导出位置");
        add(jButton3);

        JTextField jTextField2 = new JTextField();
        jTextField2.setPreferredSize(new Dimension(380, 30));
        jTextField2.setText("点击选取视频导出文件夹");
        jTextField2.setEditable(false);
        add(jTextField2);

        JButton jButton2 = new JButton("合成");
        add(jButton2);

        JLabel jLabel = new JLabel("合成进度");
        JLabel jLabel2 = new JLabel("0");
        JLabel jLabel3 = new JLabel("/");
        JLabel jLabel4 = new JLabel("0");
        add(jLabel);
        add(jLabel2);
        add(jLabel3);
        add(jLabel4);

        JTextArea jTextArea = new JTextArea();
        JScrollPane jScrollPane = new JScrollPane(jTextArea);
        jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        jScrollPane.setPreferredSize(new Dimension(380, 520));
        jTextArea.setEditable(false);
        add(jScrollPane);

        // 选取视频所在目录
        jButton.addActionListener(e -> {
            m3u8Files = new ArrayList<>();
            JFileChooser chooser = new JFileChooser("C:");
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
            int returnVal = chooser.showOpenDialog(this);
            jTextArea.append("* 选取视频目录 *\n");
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                jTextField.setText(chooser.getSelectedFile().getAbsolutePath());
                // 分析该路径下的文件
                isHaveWannaMergeFile(chooser.getSelectedFile().getAbsolutePath(), jTextArea, jLabel4);
//                 test(chooser.getSelectedFile().getAbsolutePath());
            }
        });
        // 选取导出目录
        jButton3.addActionListener(e -> {
            JFileChooser chooser = new JFileChooser("C:/m3u8");
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int returnVal = chooser.showOpenDialog(this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                jTextField2.setText(chooser.getSelectedFile().getAbsolutePath());
                // test(chooser.getSelectedFile().getAbsolutePath());
            }
        });

        // 合成按钮
        /** 合成的视频
         * 1. 遍历m3u8文件数组
         * 2. 打开m3u8文件，收集待合成文件数组
         * 3. 组合m3u8最终文件名，开始合成；合成成功则更新合成进度
         */
        jButton2.addActionListener(e -> {
            if (m3u8Files.size() < 1) {
                jTextArea.append("没有可以合成的m3u8文件\n");
            }
            String outputPath = jTextField2.getText();
            if (outputPath.isEmpty() || "点击选取视频导出文件夹".equals(outputPath)) {
                jTextArea.append("请选择视频导出目录\n");
                return;
            }
            for (M3U8Object m3u8 : m3u8Files) {

                String jLabel2Val = jLabel2.getText();
                int jLabel2ValInt = Integer.parseInt(jLabel2Val);
                jTextArea.append("正在合成第" + (jLabel2ValInt+1) + "个\n");
                try {
                    CountDownLatch countDownLatch = new CountDownLatch(1);
                    new Thread(() -> {
                        MergeMoreFile(getMergeFiles(m3u8.getAbsPath()), outputPath.replace("/", "\\") + "\\" + m3u8.getFilename() + ".mp4");
                        countDownLatch.countDown();
                    }).start();
                    countDownLatch.await();
                } catch (Exception ex) {
                    jTextArea.append(m3u8.getFilename() + "转换失败");
                }
                jLabel2ValInt++;
                jLabel2.setText(String.valueOf(jLabel2ValInt));

            }
            m3u8Files = new ArrayList<>();
            jTextField.setText("");
            jLabel2.setText("0");
            jLabel4.setText("0");
        });
    }


    /** 分析该路径下的文件
     * 1. 先检查是否含有.m3u8开头的文件；有则进行第2步
     * 2. 统计m3u8文件个数，汇总到m3u8Files数组中(每个m3u8文件都有其对应的待合成文件数组)，并输出到文本域
     */
    public void isHaveWannaMergeFile(String path, JTextArea jTextArea, JLabel jLabel4) {
        File file = new File(path);
        if (file.isFile()) {
            // 读取文件，收集待合成文件数组
            if (file.getName().lastIndexOf(".m3u8") != -1 || file.getName().lastIndexOf(".M3U8") != -1) {
                M3U8Object m3U8Object = new M3U8Object();
                m3U8Object.setFilename(file.getName().substring(0, file.getName().lastIndexOf(".")));
                m3U8Object.setAbsPath(file.getPath());
                m3U8Object.setMergeFiles(readM3u8File(file));
                m3u8Files.add(m3U8Object);
                jLabel4.setText("1");
            } else {
                jTextArea.append("选择的文件不是m3u8文件\n");
            }
            return;
        }
        File[] tempList = file.listFiles();
        for (File file1 : tempList) {
            jTextArea.append(file1.getName() + "\n");
            if (file1.isFile()) {
                if (file1.getName().lastIndexOf(".m3u8") != -1 || file1.getName().lastIndexOf(".M3U8") != -1) {
                    M3U8Object m3U8Object = new M3U8Object();
                    m3U8Object.setFilename(file1.getName().substring(0, file1.getName().lastIndexOf(".")));
                    m3U8Object.setAbsPath(file1.getPath());
                    m3U8Object.setMergeFiles(readM3u8File(file1));
                    m3u8Files.add(m3U8Object);
                }
            }
        }
        jTextArea.append("共扫描到" + m3u8Files.size() + "个m3u8文件\n");
        jLabel4.setText(String.valueOf(m3u8Files.size()));
    }

    public java.util.List<File> getMergeFiles(String path) {
        List<String> strings = readM3u8File(new File(path));
        List<File> files = new ArrayList<>();
        for (String str : strings) {
            files.add(new File(str));
        }
        return files;
    }

    /**
     * 从文件中读取所有的行
     * @param file 文件
     * @return 所有的行
     */
    public java.util.List<String> readM3u8File(File file) {
        java.util.List<String> list = new ArrayList<>();
        try {
            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String str;
            while ((str = bufferedReader.readLine()) != null) {
                if (str.startsWith("/")) {
                    list.add(file.getParent() + "\\" + str.split("//")[1].replace("/", "\\"));
                }
            }
            bufferedReader.close();
            fileReader.close();
        } catch (IOException e) {
            return new ArrayList<>();
        }
        return list;
    }

    /**
     * 合并所有文件
     * @param files 被合并的文件列表
     * @param filepath 将要合并成的目标; 绝对路径，example：/home/xx/video/1.mp4
     */
    public void MergeMoreFile(java.util.List<File> files, String filepath) {
        File file = new File(filepath);
        if (file.exists()) {
            System.out.println("文件已经存在，合并终止");
            return;
        }
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            byte[] b = new byte[4096];
            for (File strFile : files) {
                FileInputStream fileInputStream = new FileInputStream(strFile);
                int len;
                while ((len = fileInputStream.read(b)) != -1) {
                    fileOutputStream.write(b, 0, len);
                }
                fileInputStream.close();
                fileOutputStream.flush();
            }
            fileOutputStream.close();
        } catch (Exception e) {
            return;
        }
    }
}
